package com.kindnesslibrary.network;

import android.os.Build;
import android.text.TextUtils;

import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.HttpStatus;
import org.apache.http.NameValuePair;
import org.apache.http.client.HttpClient;
import org.apache.http.client.entity.UrlEncodedFormEntity;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.entity.mime.MultipartEntity;
import org.apache.http.entity.mime.content.ContentBody;
import org.apache.http.entity.mime.content.FileBody;
import org.apache.http.entity.mime.content.StringBody;
import org.apache.http.impl.client.DefaultHttpClient;
import org.apache.http.message.BasicNameValuePair;
import org.apache.http.params.BasicHttpParams;
import org.apache.http.params.HttpConnectionParams;
import org.apache.http.params.HttpParams;
import org.apache.http.util.EntityUtils;

import java.io.ByteArrayOutputStream;
import java.io.DataOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.HttpURLConnection;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.UUID;

/**
 * Created by chenhongxin on 2017/5/7.
 * Http网络请求工具类
 */
public class HttpUtils {

    private HttpConfig httpConfig = HttpConfig.getInstance(); // http配置参数
    private static final int CONNECTION_TIMEOUT = 30000; // 连接超时

    private static HttpUtils httpUtils; // 单例

    /**
     * 私有构造
     */
    private HttpUtils() {

    }

    public static HttpUtils getInstance() {
        if (httpUtils == null) {
            synchronized (HttpUtils.class) {
                if (httpUtils == null) {
                    httpUtils = new HttpUtils();
                }
            }
        }
        return httpUtils;
    }

    /**
     * post请求
     *
     * @param url    请求路径
     * @param params 参数
     * @return
     */
    public String post(String url, Map<String, String> params) {
        if (TextUtils.isEmpty(url)) {
            throw new NullPointerException("url不能为空");
        }
        String path = "";
        if (url.contains("http")) {
            path = url;
        } else {
            path = httpConfig.getIp() + url;
        }
        if (Build.VERSION.SDK_INT <= Build.VERSION_CODES.KITKAT) {
            return lowVersion(path, params, HttpManager.RequestWay.POST);
        } else {
            return heightVersion(path, params, HttpManager.RequestWay.POST);
        }
    }

    /**
     * post请求
     *
     * @param url    请求路径
     * @param params 参数
     * @return
     */
    public String get(String url, Map<String, String> params) {
        if (TextUtils.isEmpty(url)) {
            throw new NullPointerException("url不能为空");
        }
        String path = "";
        if (url.contains("http")) {
            path = url;
        } else {
            path = httpConfig.getIp() + url;
        }
        if (Build.VERSION.SDK_INT <= Build.VERSION_CODES.KITKAT) {
            return lowVersion(path, params, HttpManager.RequestWay.GET);
        } else {
            return heightVersion(path, params, HttpManager.RequestWay.GET);
        }
    }

    public String singlePploadFile(File file, String url, String fileParam, Map<String, String> params){
        if (TextUtils.isEmpty(url)) {
            throw new NullPointerException("url不能为空");
        }
        String path = "";
        if (url.contains("http")) {
            path = url;
        } else {
            path = httpConfig.getIp() + url;
        }
        if (Build.VERSION.SDK_INT <= Build.VERSION_CODES.KITKAT) {
            return singleFileUploadLow(file, path, fileParam, params);
        } else {
            return singleFileUploadHeight(file, path, fileParam, params);
        }
    }

    /**
     * 低版本手机网络请求
     *
     * @param url        请求路径
     * @param params     参数
     * @param requestWay 请求方式：POST、GET
     * @return
     */
    private String lowVersion(String url, Map<String, String> params, HttpManager.RequestWay requestWay) {
        HttpParams httpParams = new BasicHttpParams();
        HttpConnectionParams.setConnectionTimeout(httpParams, CONNECTION_TIMEOUT);
        HttpConnectionParams.setSoTimeout(httpParams, CONNECTION_TIMEOUT);
        HttpClient httpClient = new DefaultHttpClient(httpParams);
        if (requestWay == HttpManager.RequestWay.POST) {
            HttpPost post = new HttpPost(url);
            post.setParams(httpParams);
            try {
                List<NameValuePair> list = new ArrayList<NameValuePair>();
                for (String key : params.keySet()) {
                    list.add(new BasicNameValuePair(key, params.get(key)));
                }
                post.setEntity(new UrlEncodedFormEntity(list, "UTF-8"));
                HttpResponse response = httpClient.execute(post);
                if (response.getStatusLine().getStatusCode() == HttpStatus.SC_OK) {
                    HttpEntity entity = response.getEntity();
                    String result = EntityUtils.toString(entity, "UTF-8");
                    return result;
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        } else {
            url = url + generateParams(params);
            HttpGet get = new HttpGet(url);
            get.setParams(httpParams);
            try {
                HttpResponse response = httpClient.execute(get);
                if (response.getStatusLine().getStatusCode() == HttpStatus.SC_OK) {
                    HttpEntity entity = response.getEntity();
                    String result = EntityUtils.toString(entity, "UTF-8");
                    return result;
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        return "";
    }

    /**
     * 4.4版本以上的手机网络请求方式
     *
     * @param path       请求路径
     * @param params     参数
     * @param requestWay 请求方式
     * @return
     */
    private String heightVersion(String path, Map<String, String> params, HttpManager.RequestWay requestWay) {
        HttpURLConnection connection = null;
        ByteArrayOutputStream baos = new ByteArrayOutputStream();
        InputStream in = null;
        try {
            path = path + generateParams(params);
            URL url = new URL(path);
            connection = (HttpURLConnection) url.openConnection();
            connection.setConnectTimeout(CONNECTION_TIMEOUT);
            connection.setReadTimeout(CONNECTION_TIMEOUT);
            connection.setDoInput(true);
            if (requestWay == HttpManager.RequestWay.POST) {
                connection.setRequestMethod("POST");
            } else {
                connection.setRequestMethod("GET");
            }
            if (connection.getResponseCode() == HttpStatus.SC_OK) {
                in = connection.getInputStream();
                int len = 0;
                byte[] buffer = new byte[1024];
                while ((len = in.read(buffer)) > 0) {
                    baos.write(buffer, 0, len);
                }
                String result = baos.toString();
                return result;
            }
        } catch (MalformedURLException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            if (in != null) {
                try {
                    in.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            if (baos != null) {
                try {
                    baos.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
        return "";
    }

    /**
     * 低版本手机网络请求
     * 单文件上传
     * @param file 文件
     * @param path 访问路径
     * @param fileParam 文件参数名称
     * @param params 参数
     * @return
     */
    private String singleFileUploadLow(File file, String path, String fileParam, Map<String, String> params) {
        HttpParams httpParams = new BasicHttpParams();
        HttpConnectionParams.setConnectionTimeout(httpParams, CONNECTION_TIMEOUT);
        HttpConnectionParams.setSoTimeout(httpParams, CONNECTION_TIMEOUT);
        HttpPost post = new HttpPost(path);
        HttpClient client = new DefaultHttpClient(httpParams);
        MultipartEntity multipartEntity = new MultipartEntity();
        try {
            ContentBody contentBody = new FileBody(file);
            multipartEntity.addPart(fileParam, contentBody);
            for (Map.Entry<String, String> entries : params.entrySet()) {
                multipartEntity.addPart(entries.getKey(), new StringBody(entries.getValue()));
            }
            post.setEntity(multipartEntity);
            HttpResponse response = client.execute(post);
            if (response.getStatusLine().getStatusCode() == HttpStatus.SC_OK) {
                String result = EntityUtils.toString(response.getEntity(), "UTF-8");
                return result;
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
        return "";
    }

    /**
     * 4.4以上版本单文件上传
     * @param file
     * @param path
     * @param fileParam
     * @param params
     * @return
     */
    private String singleFileUploadHeight(File file, String path, String fileParam, Map<String, String> params) {
        String BOUNDARY = UUID.randomUUID().toString(); // 边界标识 随机生成
        String PREFIX = "--", LINE_END = "\r\n";
        String CONTENT_TYPE = "multipart/form-data"; // 内容类型
        InputStream is = null;
        InputStream input = null;
        ByteArrayOutputStream baos = new ByteArrayOutputStream();
        try {
            path = path + generateParams(params);
            URL url = new URL(path);
            // 设置连接参数
            HttpURLConnection conn = (HttpURLConnection) url.openConnection();
            conn.setReadTimeout(CONNECTION_TIMEOUT);
            conn.setConnectTimeout(CONNECTION_TIMEOUT);
            conn.setDoInput(true); // 允许输入流
            conn.setDoOutput(true); // 允许输出流
            conn.setUseCaches(false); // 不允许使用缓存
            conn.setRequestProperty("Charset", "utf-8"); // 设置编码
            conn.setRequestProperty("connection", "keep-alive");
            conn.setRequestProperty("Content-Type", CONTENT_TYPE + ";boundary=" + BOUNDARY);
            // 将网络的输出流转成二进制流
            DataOutputStream dos = new DataOutputStream(conn.getOutputStream());
            StringBuffer sb = new StringBuffer();
            sb.append(PREFIX);
            sb.append(BOUNDARY);
            sb.append(LINE_END);
            sb.append("Content-Disposition: form-data; name=\"" + fileParam + "\"; filename=\""
                    + file.getName() + "\"" + LINE_END);
            sb.append(LINE_END);
            // 将上传的格式分装的参数写入二进制流
            dos.write(sb.toString().getBytes());
            /**
             * 将文件写入二进制流
             */
            is = new FileInputStream(file);
            byte[] bytes = new byte[1024];
            int len = 0;
            while ((len = is.read(bytes)) != -1) {
                dos.write(bytes, 0, len);
            }
            is.close();
            // 换行
            dos.write(LINE_END.getBytes());
            // 合成结尾符
            byte[] end_data = (PREFIX + BOUNDARY + PREFIX + LINE_END).getBytes();
            dos.write(end_data);
            dos.flush();
            int code = conn.getResponseCode();
            if (code == 200) {
                input = conn.getInputStream();
                while ((len = input.read(bytes)) != -1) {
                    baos.write(bytes, 0, len);
                }
                byte[] result = baos.toByteArray();
                String response = new String(result);
                return response;
            }
        } catch (MalformedURLException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
        return "";
    }

    /**
     * 把参数以key-value-&拼接
     *
     * @param params 参数
     * @return
     */
    private String generateParams(Map<String, String> params) {
        StringBuilder builder = new StringBuilder();
        String result = "";
        for (Map.Entry<String, String> entries : params.entrySet()) {
            builder.append(entries.getKey() + "=" + entries.getValue() + "&");
        }
        if (!builder.toString().equals("")) {
            result = "?" + builder.deleteCharAt(builder.length() - 1).toString();
        }
        return result;
    }

}
